#include<iostream>
#include"R_iterator.h"
using std::swap;
using namespace MyRI; 
namespace MyL
{
  template<class T>
    struct ListNode{
        ListNode(const int date = 0)
        :_date(date)
         ,_next(nullptr)
         ,_prev(nullptr)
        {}
        T _date;
        ListNode* _next;
        ListNode* _prev;
    };
  template<class T,class poi,class ref>
    struct List_Iterator{
      typedef ListNode<T> Node; 
      List_Iterator(Node* node)
      :_iterator(node)
      {}
      List_Iterator& operator++()
      {
        _iterator = _iterator->_next;
        return *this;
      }
      List_Iterator operator++(int)
      {
        List_Iterator tmp = *this;
        _iterator = _iterator->_next;
        return tmp;
      }
      List_Iterator operator--()
      {
        _iterator = _iterator->_prev;
        return *this;
      }
      List_Iterator operator--(int)
      {
        List_Iterator tmp = *this;
        _iterator = _iterator->_prev;
        return tmp;
      }
      bool operator!=(List_Iterator it)
      {
        if(_iterator != it._iterator)
        {
          return true;
        }
        else{
          return false;
        }
      }
      ref operator*()
      {
        return _iterator->_date;
      }
      poi operator->()
      {
        return &(_iterator->_date);
      }
      Node* _iterator;
    };

  template<class T>
    class list{
      public:
        typedef ListNode<T> Node; 
        typedef List_Iterator<T,T*,T&> iterator;
        typedef List_Iterator<const T,const T*,const T&> const_iterator;
        typedef Reverse_Iterator<T,iterator> reverse_iterator;
        typedef Reverse_Iterator<T,const_iterator> conse_reverse_iterator;
        list()
        :_head(new Node)
        {
          _head->_next = _head;
          _head->_prev = _head;
        }
        template<class IteratorBegin,class IteratorEnd>
        list(const IteratorBegin begin,const IteratorEnd end)
        {
          auto it = begin;
          while(begin != end)
          {
            push_back(*it);
            it++;
          }
        }
        list(const list& l)
        {
          auto it = l.begin();
          while(it != l.end())
          {
            push_back(*it);
            it++;
          }
        }
        void swap(const list l)
        {
          std::swap(_head,l._head);
        }
        list& operator=(list l)
        {
          swap(l);
          return *this;
        }
        iterator begin()
        {
          return iterator(_head->_next);
        }
        const_iterator begin(int) const
        {
          return const_iterator(_head->next);
        }
        reverse_iterator rbegin()
        {
          return reverse_iterator(end()); 
        }
        iterator end()
        {
          return iterator(_head);
        }
        const_iterator end(int) const
        {
          return const_iterator(_head);
        }
        reverse_iterator rend()
        {
          return reverse_iterator(begin());
        }

        void push_back(const T& date)
        {
        //  Node* newnode = new Node(date);
        //  // head  endnode newnode
        //  Node* endnode = _head->_prev; 
        //  endnode->_next = newnode;
        //  newnode->_prev = endnode;
        //  newnode->_next = _head;
        //  _head->_prev = newnode;
            insert(_head,date);
        }
        void pop_back()
        {
          erase(iterator(_head->_prev));
        }
        iterator insert(iterator it,const T& date)
        {
          Node* pos = it._iterator;
          Node* prev = pos->_prev;
         Node* newnode = new Node(date); 
          //prev newnode pos
          prev->_next = newnode;
          newnode->_prev = prev;
          newnode->_next = pos;
          pos->_prev = newnode;
          return iterator(newnode);
        }
        iterator erase(iterator it)
        {
          Node* pos = (it._iterator);
          Node* prev = pos->_prev;
          Node* next = pos->_next;
          // prev pos next 
          prev->_next = next;
          next->_prev = prev;
          delete pos;
          return iterator(next);
        }

    private:
      Node* _head;
    };
}
